package cs4game;

import java.awt.*;

import javax.swing.*;
@SuppressWarnings("serial")
public class MazeCell extends JPanel{
	private boolean[] borders; //An array for the borders of the cell.
	public static final int UP = 0, RIGHT = 1, DOWN=2, LEFT = 3; //Directions each way, up, down, left, and right.
	//Multiple different status possibilities, including blank, visited, dead, or directional current (which way the mouse points).
	public static final int BLANK=0, VISITED=1, DEAD=2, CURRENTUP = 3, CURRENTRIGHT = 4, CURRENTDOWN = 5, CURRENTLEFT = 6;
	public boolean isEnd = false; //A boolean stating if this is the final square.
	//An array of colors cooresponding to each status integer.
	private Color[] colors = {Color.WHITE, Color.BLUE, Color.RED, Color.WHITE,Color.WHITE, Color.WHITE, Color.WHITE,};
	public MazeCell[][] mazey; //An array of all of the mazecells, so adjacent ones can be found.
	private int status; //The current status uf the cell
	private int row, col; //The cell's row and column in the maze

	
	
	public MazeCell(int r, int c, boolean b, MazeCell[][] m){
		super(); //Calls JPanel's default constructor.
		//Sets the row and column to the provided r and c, and the MazeCell[][] as m.
		row =r;
		col = c;
		mazey = m;
		
		borders = new boolean[4]; //Makes borders as a new boolean array, setting each as true (existing)
		for(int i=0; i<4; i++)
			borders[i] = true;
		
		//Sets the background as white, status as blank, and tells it to ignore repaints.
		this.setBackground(Color.WHITE);
		this.setIgnoreRepaint(true);
		status = BLANK;
	}

	public void setIsEnd(boolean b){isEnd = b;}
	public int row(){return row;}
	public int col(){return col;}

	public void setStatus(int x){status = x;}
	public boolean isBlank(){return status==BLANK;}
	public boolean isVisited(){return status==VISITED;}
	public boolean isDead(){return status==DEAD;}
	public boolean blocked(int dir){return borders[dir];} //is there a border in this direction

	//Sets this as the start square. Points the (CURRENT) mouse image to the first non-border
	//direction found, clockwise.
	public void setStart(){
		if(borders[UP] == false)
			status = CURRENTUP;
		if(borders[RIGHT] == false)
			status = CURRENTRIGHT;
		if(borders[DOWN] == false)
			status = CURRENTDOWN;
		if(borders[LEFT] == false)
			status = CURRENTLEFT;
	}
	

	//Used to set the status of this border and the adjacent one.
	//If t is true, adds the border. If t is false, removes it.
	public void setBoth(int border, boolean t){
		//If the border inputed is up, set both this and the above cell to have the proper border.
		if(border == UP){
			if(t){
				drawUp();
				mazey[row-1][col].drawDown();
			}
			else{
				clearUp();
				mazey[row-1][col].clearDown();
			}
		}
		//If the border inputed is down, set both this and the above cell to have the proper border.
		if(border == DOWN){
			if(t){
				drawDown();
				mazey[row+1][col].drawUp();
			}
			else{
				clearDown();
				mazey[row+1][col].clearUp();
			}
		}
		
		//If the border inputed is left, set both this and the above cell to have the proper border.
		if(border == LEFT){
			if(t){
				drawLeft();
				mazey[row][col-1].drawRight();
			}
			else{
				clearLeft();
				mazey[row][col-1].clearRight();
			}
		}
		
		//If the border inputed is right, set both this and the above cell to have the proper border.
		if(border == RIGHT){
			if(t){
				drawRight();
				mazey[row][col+1].drawLeft();
			}
			else{
				clearRight();
				mazey[row][col+1].clearLeft();
			}
		}
	
		
	}

	//Removes or draws the border in a respective direction, also repainting.
	public void clearUp(){borders[UP] = false; repaint();}
	public void clearDown(){borders[DOWN] = false; repaint();}
	public void clearRight(){borders[RIGHT] = false; repaint();}
	public void clearLeft(){borders[LEFT] = false; repaint();}
	public void drawUp(){borders[UP] = true; repaint();}
	public void drawDown(){borders[DOWN] = true; repaint();}
	public void drawRight(){borders[RIGHT] = true; repaint();}
	public void drawLeft(){borders[LEFT] = true; repaint();}

	//Returns the direction to a specific cell, will not work for diagonals.
	public int directionTo(MazeCell c){
		//For example, if the dest row is more than this, then return down. So on and so forth.
		if(row()>c.row())
			return UP;
		if(row()<c.row())
			return DOWN;
		if(col()<c.col())
			return RIGHT;
		if(col()>c.col())
			return LEFT;
		return -1;
	}
	
	//Paints this with a specific width, height, x and y displacement.
	public void paintComponent(Graphics g, int w, int h, int wid, int hid){
		//Fills a rectangle as the background with the appropriate color for this's status.
		g.setColor(colors[status]);
		g.fillRect(w, h, wid, hid);
		
		//Sets the color to black, and draws every border that is set to true.
		g.setColor(Color.BLACK);
		if(borders[UP])
			g.drawLine(w,h,wid+w, h);
		if(borders[RIGHT])
			g.drawLine(w+wid,h,w+wid,h+hid);
		if(borders[DOWN])
			g.drawLine(w,h+hid,wid+w,hid+h);
		if(borders[LEFT])
			g.drawLine(w,h,w,h+hid);
		
		//If this is the final square, draw a piece of cheese on it.
		if(isEnd)
			g.drawImage(Toolkit.getDefaultToolkit().getImage("./endSquare.png"), w, h, wid, hid, null);
		
		//A switch block to draw a specific mouse image pointing in a diff. direction depending on the status.
		switch(status){
		//Normally, just set the background to the status color.
		default: 
			this.setBackground(colors[status]);
			break;
		//Otherwise, if the mouse should 'look' up, make it do that. For down, left, right, the same.
		case 3:
			g.drawImage(Toolkit.getDefaultToolkit().getImage("./mouseUP.png"), w, h, wid, hid, null);
			break;
		case 4:
			g.drawImage(Toolkit.getDefaultToolkit().getImage("./mouseRIGHT.png"), w, h, wid, hid, null);
			break;
		case 5:
			g.drawImage(Toolkit.getDefaultToolkit().getImage("./mouseDOWN.png"), w, h, wid, hid, null);
			break;
		case 6:
			g.drawImage(Toolkit.getDefaultToolkit().getImage("./mouseLEFT.png"), w, h, wid, hid, null);
			break;
		}
	}
	
	//Removes functions so the system doesn't repaint it.
	public void paint(Graphics g){}
	public void repaint(){}
	public void paintComponent(Graphics g){}
	public void update(Graphics g){}

}
